﻿using EMall.Query;
using Microsoft.Extensions.Primitives;
using Yarp.ReverseProxy.Configuration;

namespace EMall.AdminGateway
{
    public class YarpProxyConfigProvider : IProxyConfigProvider, IDisposable
    {
        private readonly IYarpProxyConfigStore _proxyConfigStore;
        private YarpProxyConfig _proxyConfig;
        private CancellationTokenSource _changeToken;
        private bool _disposed;
        private IDisposable _subscription;
        public YarpProxyConfigProvider(IYarpProxyConfigStore proxyConfigStore)
        {
            _proxyConfigStore = proxyConfigStore;
        }
        public IProxyConfig GetConfig()
        {
            if (_proxyConfig == null)
            {
                //_subscription = ChangeToken.OnChange(_strore.GetReloadToken, UpdateConfig);
                UpdateConfigAsync().Wait();
            }
            return _proxyConfig;
        }
        private async Task UpdateConfigAsync()
        {
            YarpProxyConfig newConfig = null;
            try
            {
                newConfig = await _proxyConfigStore.GetConfigAsync() as YarpProxyConfig;
            }
            catch (Exception)
            {
                if (_proxyConfig == null)
                {
                    throw;
                }
                return;
            }
            var oldToken = _changeToken;
            _changeToken = new CancellationTokenSource();
            newConfig.ChangeToken = new CancellationChangeToken(_changeToken.Token);
            _proxyConfig = newConfig;
            try
            {
                oldToken?.Cancel(throwOnFirstException: false);
            }
            catch (Exception ex)
            {
            }
        }
        public void Dispose()
        {
            if (!_disposed)
            {
                _subscription?.Dispose();
                _changeToken?.Dispose();
                _disposed = true;
            }
        }
    }
    public static class YarpProxyConfigProviderExtensions
    {
        public static IReverseProxyBuilder LoadFromStore(this IReverseProxyBuilder builder)
        {
            builder.Services.AddSingleton<IYarpProxyConfigStore, YarpProxyConfigStore>();
            builder.Services.AddSingleton<IProxyConfigProvider>(serviceProvider =>
            {
                var aa = serviceProvider.GetRequiredService<IQueryService>();
                return new YarpProxyConfigProvider(serviceProvider.GetRequiredService<IYarpProxyConfigStore>());
            });
            return builder;
        }
    }
}
